home *** CD-ROM | disk | FTP | other *** search
/ PsL Monthly 1993 December / PSL Monthly Shareware CD-ROM (December 1993).iso / prgmming / dos / c / date_ag.com / DATES.C < prev    next >
Encoding:
C/C++ Source or Header  |  1993-06-03  |  15.4 KB  |  475 lines

  1. /*-------------------------------------------------------------------------
  2. **   DATES.C
  3. **
  4. **   Written By: Al Gifford
  5. **
  6. **   March 26, 1993
  7. **
  8. **   (c)Copyright 1993 All Rights Reserved
  9. **
  10. **   This collection of functions can greatly simplify any programming
  11. **   you need to do which involves the use of dates.  Nothing is asked in
  12. **   return for using this code other than to give credit where credit is
  13. **   due.  If you use any portion of this code, or derive ideas from it,
  14. **   you must make mention of that fact in your documentation (written or
  15. **   electronic) and/or in the program itself.  Failure to do so is
  16. **   plagiarism and is in violation of the Copyright laws.
  17. */
  18.  
  19. #include<stdio.h>
  20. #include<dos.h>
  21. #include<conio.h>
  22. #include<string.h>
  23. #include<stdlib.h>
  24.  
  25. short Calendar(struct date d);
  26. struct date ConvertGregorian(long JulianDate);
  27. unsigned short ConvertJulian(char day,char month,short year);
  28. short CountLeapYear(short year1,short year2);
  29. short DaysInMonth(char month,short year);
  30. char  DayOfWeek(char day,char month,short year);
  31. short DayOfYear(char day,char month,short year);
  32. char  IsValidDate(char day,char month,short year);
  33. short LeapYear(short year);
  34. char *MonthName(char month);
  35. struct date ParseDate(char *dateString);
  36. void  RevVideo(void);
  37. char *WeekdayName(char weekday);
  38.  
  39. void main(void)
  40.    {
  41.    struct date d;
  42.    unsigned short num;
  43.    char dateString[40];
  44.    char shortMonth[4];
  45.  
  46.    clrscr();
  47.    getdate(&d);
  48.    printf("\t\t\tDATE FUNCTIONS DEMONSTRATION\n\n");
  49.    printf("The current year is: %d\n",d.da_year);
  50.    printf("The current day is: %d\n",(short)d.da_day);
  51.    printf("The current month is: %d, which is %s.\n",(short)d.da_mon,MonthName(d.da_mon));
  52.    num = ConvertJulian(d.da_day,d.da_mon,d.da_year);
  53.    printf("The Julian Date is %u.\n",num);
  54.    d = ConvertGregorian(num);
  55.    printf("Converted back to Gregorian is YR:%d DA:%d MO:%d.\n",d.da_year,(short)d.da_day,(short)d.da_mon);
  56.    num = CountLeapYear(d.da_year, 1900);
  57.    printf("There were %u leap years between 1900 and %d.\n",num,d.da_year);
  58.    num = DaysInMonth(d.da_mon,d.da_year);
  59.    printf("This month has %u days.\n",num);
  60.    num = DayOfWeek(d.da_day,d.da_mon,d.da_year);
  61.    printf("(Sunday=0 - Saturday=6) Today is %u, which is %s.\n",num,WeekdayName((char)num));
  62.    num = DayOfYear(d.da_day,d.da_mon,d.da_year);
  63.    printf("Today is day %u of %d.\n",num,d.da_year);
  64.    num = IsValidDate(d.da_day,d.da_mon,d.da_year);
  65.    printf("The date entered was");
  66.    if(!(num))
  67.       printf(" not");
  68.    printf(" valid.\n");
  69.    num = LeapYear(d.da_year);
  70.    printf("This year is");
  71.    if(!(num))
  72.       printf(" not");
  73.    printf(" a leapyear.\n");
  74.    num = (unsigned)d.da_year / 100 + 1;
  75.    printf("We are in the %u",num);
  76.    if(num % 10 == 1)
  77.       printf("st");
  78.    if(num % 10 == 2)
  79.       printf("nd");
  80.    if(num % 10 == 3)
  81.       printf("rd");
  82.    else
  83.       printf("th");
  84.    printf(" century.\n");
  85.    printf("\nPress <Enter> to continue\n");
  86.    getch();
  87.    clrscr();
  88.    sprintf(dateString,"%d/%d/%d",(short)d.da_mon,(short)d.da_day,d.da_year);
  89.    printf("Todays date as a string: %s\n",dateString);
  90.    d = ParseDate(dateString);
  91.    printf("Converted back to a date structure is YR:%d DA:%d MO:%d.\n",d.da_year,(short)d.da_day,(short)d.da_mon);
  92.    strncpy(shortMonth,MonthName(d.da_mon),3);
  93.    shortMonth[3] = '\0';
  94.    strcpy(shortMonth,strupr(shortMonth));
  95.    sprintf(dateString,"%d%s%d",(short)d.da_day,shortMonth,d.da_year - d.da_year / 100 * 100);
  96.    printf("A more difficult date string: %s\n",dateString);
  97.    d = ParseDate(dateString);
  98.    printf("Converted back to a date structure is YR:%d DA:%d MO:%d.\n",d.da_year,(short)d.da_day,(short)d.da_mon);
  99.    sprintf(dateString,"Today's date is %s %d, %d",MonthName(d.da_mon),(short)d.da_day,d.da_year);
  100.    printf("An even messier date string: %s\n",dateString);
  101.    d = ParseDate(dateString);
  102.    printf("Converted back to a date structure is YR:%d DA:%d MO:%d.\n",d.da_year,(short)d.da_day,(short)d.da_mon);
  103.    gotoxy(21,12);
  104.    Calendar(d);
  105.    }
  106.  
  107. struct date ConvertGregorian(long JulianDate)
  108.    /*----------------------------------------------------------------------
  109.    **   Function returns Gregorian date using the DOS.H date structure.
  110.    **   Julian Date is number of Days since January 1, 1900 (Day 1).
  111.    */
  112.    {
  113.    short DAYS[] = {0,0,31,59,90,120,151,181,212,243,273,304,334,365};
  114.    short numDays;
  115.    struct date d;
  116.    d.da_mon = 1;
  117.  
  118.    d.da_year = (short)(JulianDate / 365.2475 + 1900);
  119.    numDays = JulianDate - (d.da_year - 1900) * 365 - CountLeapYear(d.da_year,1900);
  120.    while(DAYS[d.da_mon + 1] < numDays)
  121.       d.da_mon++;
  122.    d.da_day = numDays - DAYS[d.da_mon];
  123.    return(d);
  124.    } /* end of ConvertJulian */
  125.  
  126.  
  127. unsigned short ConvertJulian(char day,char month,short year)
  128.    /*----------------------------------------------------------------------
  129.    **   Function returns number of days for Julian date.
  130.    **   Julian Date is number of Days since January 1, 1900 (Day 1).
  131.    */
  132.    {
  133.    short DAYS[] = {0,0,31,59,90,120,151,181,212,243,273,304,334,365};
  134.    long numDays;
  135.  
  136.    numDays = DAYS[month] + day;
  137.    if(LeapYear(year) && month > 2)
  138.       numDays++;
  139.    numDays += ((year - 1900) * 365 + CountLeapYear(year,1900));
  140.    return(numDays);
  141.    } /* end of ConvertJulian */
  142.  
  143. short CountLeapYear(short year1,short year2)
  144.    {
  145.    /*----------------------------------------------------------------------
  146.    **   Function counts number of leapyears between two years.
  147.    **   Years must have all 4 digits.
  148.    */
  149.    short count = 0;
  150.    short small;
  151.    short large;
  152.  
  153.    small = year1 < year2 ? year1 : year2;
  154.    large = year1 > year2 ? year1 : year2;
  155.    for(small = small;small < large;small++)
  156.       {
  157.       if(LeapYear(small))
  158.       count++;
  159.       }
  160.    return(count);
  161.    } /* end of CountLeapYear */
  162.  
  163. short DaysInMonth(char month,short year)
  164.    /*----------------------------------------------------------------------
  165.    **   Function returns the number of days in a given month.
  166.    **   The month is 1-12 and the year must have all 4 digits.
  167.    */
  168.    {
  169.    short DAYS[] = {0,0,31,59,90,120,151,181,212,243,273,304,334,365};
  170.    char leapDay;
  171.  
  172.    if(month == 2 && LeapYear(year))
  173.       leapDay = 1;
  174.    else
  175.       leapDay = 0;
  176.  
  177.    return(DAYS[month + 1] - DAYS[month] + leapDay);
  178.    } /* end of DaysInMonth */
  179.  
  180. char DayOfWeek(char day,char month,short year)
  181.    /*----------------------------------------------------------------------
  182.    **   Function returns the day of the week (0-6 : Sunday-Saturday).
  183.    */
  184.    {
  185.    return(ConvertJulian(day,month,year) % 7);
  186.    } /* end of DayOfWeek */
  187.  
  188. short DayOfYear(char day,char month,short year)
  189.    /*----------------------------------------------------------------------
  190.    **   Function returns number of days for date in current year.
  191.    */
  192.    {
  193.    short DAYS[] = {0,0,31,59,90,120,151,181,212,243,273,304,334,365};
  194.    short numDays;
  195.  
  196.    numDays = DAYS[month] + day;
  197.    if(LeapYear(year) && month > 2)
  198.       numDays++;
  199.    return(numDays);
  200.    } /* end of DayOfYear */
  201.  
  202. char IsValidDate(char day,char month,short year)
  203.    /*----------------------------------------------------------------------
  204.    **   Function returns 1 if date is valid, otherwise returns 0.
  205.    **   Note: Dates earlier than 1900 are not supported by these functions.
  206.    */
  207.    {
  208.    if(year < 1900)
  209.       return(0);
  210.    if(month > 12 || month < 1)
  211.       return(0);
  212.    if(day > DaysInMonth(month,year) || day < 1)
  213.       return(0);
  214.    else
  215.       return(1);
  216.    } /* end of IsValidDate */
  217.  
  218. short LeapYear(short year)
  219.    /*----------------------------------------------------------------------
  220.    **   Function returns true (1) if year (all 4 digits) is a leap year,
  221.    **      otherwise it returns false(0).
  222.    */
  223.    {
  224.    if(!(year % 4) && (year % 100 || !(year % 400)))
  225.       return(1);
  226.    else
  227.       return(0);
  228.    } /* end of LeapYear */
  229.  
  230. char *MonthName(char month)
  231.    {
  232.    /*-------------------------------------------------------------------------
  233.    **   Arrays to convert numbers to words.
  234.    **
  235.    **   Helpful hints:
  236.    **      To get abbreviations use strncpy() for desired length.
  237.    **      To get upper case use strupr().
  238.    **      To get lower case use strlwr().
  239.    */
  240.    char *MONTHNAME[] = {"","January","February","March","April","May","June","July","August","September","October","November","December"};
  241.    return(MONTHNAME[month]);
  242.    } /* end of MonthName */
  243.  
  244. struct date ParseDate(char *dateString)
  245.    /*----------------------------------------------------------------------
  246.    **   Psuedo-intelligent date parsing function which handles common date
  247.    **   formats including alpha and numeric months, in many different date
  248.    **   styles.   The function assumes that a year value of less than 100
  249.    **   is actually a 2 character abbreviation and will add the current
  250.    **   century to the returned year value.  The function also assumes that
  251.    **   the month will preceed the day, and that both will preceed the
  252.    **   year.  While this is only a problem for the month and day if the
  253.    **   month and day are both numeric, for non-US standard date formats,
  254.    **   the month and day will need to be swapped if the day value is 12 or
  255.    **   less.
  256.    **
  257.    **   Note - If an alpha representation of the month is used, the
  258.    **   function will enter the month and day values correctly regardless
  259.    **   of the order in which they appear in the date string.
  260.    */
  261.    {
  262.    typedef enum{
  263.      LETTER, DIGIT, SPECIAL
  264.       } CHAR_CODE;
  265.  
  266.    CHAR_CODE CHARTABLE[256];
  267.    struct date d;
  268.    short ch;
  269.    char *token;
  270.    short tokench;
  271.    short number;
  272.    char *cp = dateString;
  273.    short CENTURY;
  274.    char *MONTHSTRING = "JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC";
  275.  
  276.    /*----------------------------------------------------------------------
  277.    **   Malloc space for token.
  278.    */
  279.    if((token = (char *)malloc(strlen(dateString + 1))) == NULL)
  280.       printf("ERROR: Out of Memory.\n");
  281.  
  282.    /*----------------------------------------------------------------------
  283.    **   Initialize character table.
  284.    */
  285.    for (ch =  0 ; ch <  256; ++ch) CHARTABLE[ch] = SPECIAL;
  286.    for (ch = '0'; ch <= '9'; ++ch) CHARTABLE[ch] = DIGIT;
  287.    for (ch = 'A'; ch <= 'Z'; ++ch) CHARTABLE[ch] = LETTER;
  288.  
  289.    getdate(&d);
  290.    CENTURY = d.da_year / 100 * 100;
  291.    d.da_day = 0;
  292.    d.da_mon = 0;
  293.    d.da_year = 0;
  294.  
  295.    dateString = strupr(dateString);
  296.  
  297.    while(cp - dateString < strlen(dateString))
  298.       {
  299.       tokench = 0;
  300.       ch = *cp;
  301.       switch(CHARTABLE[ch]){
  302.      case LETTER:
  303.         while(CHARTABLE[ch] == LETTER)
  304.            {
  305.            token[tokench] = ch;
  306.            cp++;
  307.            tokench++;
  308.            ch = *cp;
  309.            }
  310.         token[tokench]='\0';
  311.         break;
  312.      case  DIGIT:
  313.         while(CHARTABLE[ch] == DIGIT)
  314.            {
  315.            token[tokench] = ch;
  316.            cp++;
  317.            tokench++;
  318.            ch = *cp;
  319.            }
  320.         token[tokench]='\0';
  321.         break;
  322.      default:
  323.         cp++;
  324.         break;
  325.      }
  326.       if(tokench && CHARTABLE[*token] == LETTER)
  327.      {
  328.      token[3] = '\0';
  329.      if(strlen(token) > 2 && strstr(MONTHSTRING,token))
  330.         {
  331.         number = (strstr(MONTHSTRING,token) - MONTHSTRING) / 3 + 1;
  332.         if(d.da_mon != 0 && d.da_day == 0)
  333.            d.da_day = d.da_mon;
  334.         d.da_mon = (char)number;
  335.         }
  336.      }
  337.       else if(tokench)
  338.      {
  339.      number = atoi(token);
  340.      if(d.da_mon == 0 && number < 13)
  341.         d.da_mon = (char)number;
  342.      else if(d.da_day == 0 && number < 32)
  343.         {
  344.         d.da_day = (char)number;
  345.         }
  346.      else if(d.da_year == 0)
  347.         {
  348.         if(number < 100)
  349.            d.da_year = CENTURY;
  350.         d.da_year += number;
  351.         }
  352.      }
  353.       }
  354.    free(token);
  355.    if(!(IsValidDate(d.da_day,d.da_mon,d.da_year)))
  356.       {
  357.       d.da_day = 0;
  358.       d.da_mon = 0;
  359.       d.da_year = 0;
  360.       }
  361.    return(d);
  362.    } /* end of ParseDate */
  363.  
  364. void RevVideo(void)
  365.    {
  366.    /*----------------------------------------------------------------------
  367.    **   Swaps foreground and background colors while preserving blink and
  368.    **   high intensity bits.
  369.    **
  370.    **   Note: If the foreground and background colors are the same, this
  371.    **         function will serve no purpose.  While it may sound ridiculous
  372.    **         to have the same foreground color as background color, it is
  373.    **         quite possible in the case where the high intensity or blink
  374.    **         foreground bits are set.  Setting either of these bits makes
  375.    **         the foreground color viewable on the background color even
  376.    **         though the colors are the same.
  377.    **
  378.    **   Text Color Bit Map:
  379.    **   ┌───┬───┬───┬───╥───┬───┬───┬───┐
  380.    **   │ 7 │ 6 │ 5 │ 4 ║ 3 │ 2 │ 1 │ 0 │
  381.    **   ├───┼───┼───┼───╫───┼───┼───┼───┤
  382.    **   │ I │ b │ b │ b ║ B │ f │ f │ f │
  383.    **   └───┴───┴───┴───╨───┴───┴───┴───┘
  384.    **   f - Foreground
  385.    **   B - Blink
  386.    **   b - Background
  387.    **   I - High Intensity
  388.    **
  389.    **   Uses:
  390.    **      <CONIO.H>
  391.    */
  392.    #define COLORSWAP(b)    (((b & 0x08) | ((b & 0x70) >> 4)) | ((b & 0x80) | ((b & 0x07) << 4)))
  393.    struct text_info ti;
  394.  
  395.    gettextinfo(&ti);
  396.    textattr(COLORSWAP(ti.attribute));
  397.    } /* End of RevVideo */
  398.  
  399. char *WeekdayName(char weekday)
  400.    {
  401.    char *WEEKDAYNAME[] = {"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"};
  402.    return(WEEKDAYNAME[weekday]);
  403.    } /* end of WeekdayName */
  404.  
  405. short Calendar(struct date d)
  406.    /*----------------------------------------------------------------------
  407.    **   The calendar function prints a calendar for the specified month.
  408.    **
  409.    **   Blink and background colors have to be shifted 4 bits to the left.
  410.    **
  411.    **    COLORS (text mode)
  412.    **   ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀│Back-│Fore-
  413.    **    Constant     │Value│grnd?│grnd?
  414.    **   ══════════════╪═════╪═════╪═════
  415.    **    BLACK        │  0  │ Yes │ Yes
  416.    **    BLUE         │  1  │ Yes │ Yes
  417.    **    GREEN        │  2  │ Yes │ Yes
  418.    **    CYAN         │  3  │ Yes │ Yes
  419.    **    RED          │  4  │ Yes │ Yes
  420.    **    MAGENTA      │  5  │ Yes │ Yes
  421.    **    BROWN        │  6  │ Yes │ Yes
  422.    **    LIGHTGRAY    │  7  │ Yes │ Yes
  423.    **    DARKGRAY     │  8  │ No  │ Yes
  424.    **    LIGHTBLUE    │  9  │ No  │ Yes
  425.    **    LIGHTGREEN   │ 10  │ No  │ Yes
  426.    **    LIGHTCYAN    │ 11  │ No  │ Yes
  427.    **    LIGHTRED     │ 12  │ No  │ Yes
  428.    **    LIGHTMAGENTA │ 13  │ No  │ Yes
  429.    **    YELLOW       │ 14  │ No  │ Yes
  430.    **    WHITE        │ 15  │ No  │ Yes
  431.    **   ──────────────┼─────┼─────┼──────
  432.    **    BLINK        │128  │ No  │ ***
  433.    */
  434.    {
  435.    short xpos = wherex(),ypos = wherey(),pos;
  436.    char  weekday[4];
  437.    short day = 0;
  438.    short monthColor = LIGHTBLUE,weekColor = GREEN,dayColor = YELLOW;
  439.  
  440.    textcolor(monthColor);
  441.    gotoxy(xpos + ((27 - strlen(MonthName(d.da_mon))) / 2),ypos);
  442.    cprintf("%s",MonthName(d.da_mon));
  443.  
  444.    gotoxy(xpos,++ypos);
  445.    textcolor(weekColor);
  446.    for(pos = 0;pos < 7;pos++)
  447.       {
  448.       strncpy(weekday,WeekdayName(pos),3);
  449.       weekday[3] = '\0';
  450.       cprintf("%s",weekday);
  451.       gotoxy(wherex() + 1,ypos);
  452.       }
  453.  
  454.    gotoxy(++xpos,++ypos);
  455.    textcolor(dayColor);
  456.    for(pos = 1;pos < 38;pos++)
  457.       {
  458.       if(pos > DayOfWeek(1,d.da_mon,d.da_year) && day < DaysInMonth(d.da_mon,d.da_year))
  459.      {
  460.      day++;
  461.      if(day == d.da_day)
  462.         RevVideo();
  463.      cprintf("%02d",day);
  464.      if(day == d.da_day)
  465.         RevVideo();
  466.      gotoxy(wherex() + 2,ypos);
  467.      }
  468.       else
  469.      gotoxy(wherex() + 4,ypos);
  470.       if(!(pos % 7))
  471.      gotoxy(xpos,++ypos);
  472.       }
  473.    gotoxy(--xpos,++ypos);
  474.    return 0;
  475.    } /* end of Calendar */